package com.pingan.haofang.searchcloud.register.metadata;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.pingan.haofang.framework.common.functional.lang.data.Try;
import com.pingan.haofang.framework.common.functional.lang.data.Tuple2;
import com.pingan.haofang.searchcloud.api.matedata.IndexMeta;
import com.pingan.haofang.searchcloud.collection.service.CollectionService;
import com.pingan.haofang.searchcloud.index.dto.IndexInfoQueryResult;
import com.pingan.haofang.searchcloud.index.service.IndexService;
import com.pingan.haofang.searchcloud.metadata.service.MetadataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 索引facade接口
 *
 * @author baojie371
 * @date 17/5/8
 * @since 1.0.0
 */
@Service("dbIndexMetadataRegister")
public class DBIndexMetadataRegister {

    private static final int MAX_NUM = 10 * 1024;

    private static final int MAX_TIME_MINUTES = 3 * 10;

    private final LoadingCache<Tuple2<String, String>, IndexMeta> metaCollectionCache = CacheBuilder.newBuilder()
            .maximumSize(MAX_NUM)
            .expireAfterWrite(MAX_TIME_MINUTES, TimeUnit.MINUTES)
            .build(new CacheLoader<Tuple2<String, String>, IndexMeta>() {
                @Override
                public IndexMeta load(Tuple2<String, String> key) throws Exception {
                    return findIndexMetaByIndexNameAndCollectionName(key.t1(), key.t2());
                }
            });


    @Autowired
    private IndexService indexService;

    @Autowired
    private CollectionService collectionService;

    @Autowired
    private MetadataService metadataService;

    public IndexMeta findIndexMetaByCollection(String indexName, String collectionName) {
        Objects.requireNonNull(indexName, "indexName is null");
        Objects.requireNonNull(collectionName, "collectionName is null");

        return Try.of(() -> metaCollectionCache.get(Tuple2.of(indexName, collectionName)))
                .orElseThrow(e -> new RuntimeException(
                        String.format("Find Index Meta Failed, indexName: %s, collectionName: %s",
                                indexName, collectionName), e));
    }

    /**
     * 清理过期的Schema和Collection
     *
     * @param indexName 索引名
     * @param topN      最旧的topN
     */
    public void clearOldConfigAndCollection(String indexName, int topN) {

        IndexInfoQueryResult index = indexService.queryByIndexNameOfStorage(indexName);

        List<Long> collectionIds = collectionService.clearOldCollectionsOfStorage(index.getBasicInfo().getId(),
                index.getBasicInfo().getEngineType(), topN);
        collectionService.clearOldCollectionsOfDb(collectionIds);

        List<Long> metadataIds = metadataService.clearOldConfigOfStorage(index.getBasicInfo().getId(),
                index.getBasicInfo().getEngineType(), topN);
        metadataService.clearOldConfigOfDb(metadataIds);
    }


    private IndexMeta findIndexMetaByIndexNameAndCollectionName(String indexName, String collectionName) {
        IndexInfoQueryResult indexInfo =
                indexService.queryByIndexNameAndCollectionNameOfStorage(indexName, collectionName);
        return IndexMetaTransfer.indexInfo2IndexMeta(indexInfo);
    }


}
